/*
 * @文件描述:
 * @版本:
 * @作者: 周晨阳
 * @Date: 2021-01-13 21:52:07
 */

#include "usart.h"
#include "rtthread.h"
#ifndef WIN_SIM

//标准库需要的支持函数
struct __FILE
{
  int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
  x = x;
}
int fputc(int ch, FILE *f)
{

  USART_SendData(USART1, (uint8_t)ch);

  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
    ;

  return (ch);
}
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
static u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15，	接收完成标志
//bit14，	接收到0x0d
//bit13~0，	接收到的有效字节数目
static u16 USART_RX_STA = 0; //接收状态标记

static uint8_t bufferReadIndex = 0;
//初始化IO 串口1
// bound:波特率
void uart_init(u32 bound)
{
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  //使能GPIOA时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟

  //串口1对应引脚复用映射
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);  //GPIOA9复用为USART1
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //GPIOA10复用为USART1

  //USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;            //复用功能
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //速度50MHz
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;          //推挽复用输出
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;            //上拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);                  //初始化PA9，PA10

  //USART1 初始化设置
  USART_InitStructure.USART_BaudRate = bound;                                     //波特率设置
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;                     //字长为8位数据格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;                          //一个停止位
  USART_InitStructure.USART_Parity = USART_Parity_No;                             //无奇偶校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 //收发模式
  USART_Init(USART1, &USART_InitStructure);                                       //初始化串口1

  USART_Cmd(USART1, ENABLE); //使能串口1

  //USART_ClearFlag(USART1, USART_FLAG_TC);

#if EN_USART1_RX
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;         //串口1中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //IRQ通道使能
  NVIC_Init(&NVIC_InitStructure);                           //根据指定的参数初始化VIC寄存器、

#endif
  printf("USART init done...\n");
}
/**
 * @brief :buffer内容准备好没
 * @param {*}
 * @return {uint8_t} 1为准备好了，0为没准备好
 */
uint8_t isUSART_bufferReady()
{
  if (USART_RX_STA & 0x8000)
  {
    // int t;
    // printf("buffer ready:\n");
    // for (t = 0; t < USART_getBufferLen(); t++)
    // {
    //   printf("%c", USART_RX_BUF[t]);
    // }
    // printf("\n");
    return 1;
  }
  return 0;
}
/**
 * @brief :清除buffer准备位
 * @param {*}
 * @return {*}
 */
void USART_clearReady()
{
  USART_RX_STA = 0;
}
/**
 * @brief :从buffer中获取一个字符
 * @param {*}
 * @return {char} 如果buffer中有数据则返回一个字符串，无数据返回0
 */
char USART_getChar()
{
  char ch = '\0';

  if (!isUSART_bufferReady())
  {
    return 0;
  }

  ch = USART_RX_BUF[bufferReadIndex];
  //printf("char:%c ,len:%d\n", ch, USART_getBufferLen());
  //buffer中所有数据都读取了
  if (bufferReadIndex == USART_getBufferLen() - 2)
  {

    bufferReadIndex = 0;
    USART_clearReady();
  }
  else
  {
    bufferReadIndex++;
  }
  return ch;
}
/**
 * @brief :获取buffer中字符串个数
 * @param {*}
 * @return {*}
 */
uint8_t USART_getBufferLen()
{
  return (USART_RX_STA & 0x3fff)+2;
}

void USART1_IRQHandler(void) //串口1中断服务程序
{
  u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
  rt_interrupt_enter();
#endif
  if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  {
    Res = USART_ReceiveData(USART1); //(USART1->DR);	//读取接收到的数据

    if ((USART_RX_STA & 0x8000) == 0) //接收未完成
    {
      if (USART_RX_STA & 0x4000) //接收到了0x0d
      {
        if (Res != 0x0a)
          USART_RX_STA = 0; //接收错误,重新开始
        else
        {
          USART_RX_BUF[(USART_RX_STA & 0X3FFF) + 1] = Res;
          USART_RX_STA |= 0x8000; //接收完成了
        }
      }
      else //还没收到0X0D
      {
        if (Res == 0x0d)
        {
          USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
          USART_RX_STA |= 0x4000;
        }
        else
        {
          USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
          USART_RX_STA++;
          if (USART_RX_STA > (USART_REC_LEN - 1))
            USART_RX_STA = 0; //接收数据错误,重新开始接收
        }
      }
    }
  }
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
  rt_interrupt_leave();
#endif
}
#endif
